package com.lorizz.picpub.index;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericField;
import org.apache.lucene.index.Term;

import com.lorizz.index.Item;
import com.lorizz.index.impl.FileSystemIndexer;
import com.lorizz.picpub.query.UpmQueries;
import com.lorizz.picpub.services.EXIF;
import com.lorizz.upm.Image;
import com.lorizz.upm.Tag;
import com.lorizz.upm.repository.Repository;

public class ImageIndexer extends FileSystemIndexer<Image> {

	private static String FILED_INDEX_ID = "image-uuid";
	private static String FIELD_ID = "id";
	private static String FIELD_COMBINED = "combined";
	private static String FIELD_CAPTION = "caption";
	private static String FIELD_TAKEN = "taken";
	private static String FIELD_UPLOADED = "uploaded";
	private static String FIELD_TAGS = "tags";
	
	private Analyzer analyzer;
	private Repository upmRepository;

	public void setAnalyzer(Analyzer analyzer) {
		this.analyzer = analyzer;
	}
	
	public void setUpmRepository(Repository upmRepository) {
		this.upmRepository = upmRepository;
	}

	@Override
	protected Document composeDocument(Item<Image> item) {
		Image image = item.getItem();
		Document doc = new Document();
		StringBuilder combined = new StringBuilder();
		// id
		doc.add(new NumericField(FIELD_ID, Field.Store.YES, true).setLongValue(image.getId()));
		// caption
		if (image.getCaption() != null) {
			doc.add(new Field(FIELD_CAPTION, image.getCaption(), Field.Store.NO, Field.Index.ANALYZED));
			combined.append(image.getCaption()).append(" ");
		}
		// taken
		if (image.getTaken() != null) 
			doc.add(new NumericField(FIELD_TAKEN, Field.Store.YES, true).setLongValue(image.getTaken().getTime()));
		// uploaded
		doc.add(new NumericField(FIELD_UPLOADED, Field.Store.YES, true).setLongValue(image.getUploaded().getTime()));
		// EXIF =====================
		combined.append(indexExif(image, doc, EXIF.MAKE, Field.Store.NO, Field.Index.ANALYZED)).append(" ");
		combined.append(indexExif(image, doc, EXIF.MODEL, Field.Store.NO, Field.Index.ANALYZED)).append(" ");
		indexExif(image, doc, EXIF.EXPOSURE_TIME, Field.Store.YES, Field.Index.NOT_ANALYZED);
		indexExif(image, doc, EXIF.ISO_SPEED_RATINGS, Field.Store.YES, Field.Index.NOT_ANALYZED);
		indexExif(image, doc, EXIF.SHUTTER_SPEED, Field.Store.YES, Field.Index.NOT_ANALYZED);
		combined.append(indexExif(image, doc, EXIF.FLASH, Field.Store.NO, Field.Index.ANALYZED)).append(" ");
		combined.append(indexExif(image, doc, EXIF.APERTURE, Field.Store.YES, Field.Index.NOT_ANALYZED)).append(" ");
		combined.append(indexExif(image, doc, EXIF.FOCAL_LENGTH, Field.Store.YES, Field.Index.NOT_ANALYZED)).append(" ");
		combined.append(indexExif(image, doc, EXIF.FOCAL_LENGTH_35MM, Field.Store.YES, Field.Index.NOT_ANALYZED)).append(" ");
		combined.append(indexExif(image, doc, EXIF.EXPOSURE_MODE, Field.Store.NO, Field.Index.ANALYZED)).append(" ");
		// combined
		doc.add(new Field(FIELD_COMBINED, combined.toString(), Field.Store.NO, Field.Index.ANALYZED));
		// tags
		if (!image.getTags().isEmpty()) {
			StringBuilder tags = new StringBuilder();
			for (Tag tag : image.getTags()) {
				tags.append(tag.getName()).append(" ");
			}
			doc.add(new Field(FIELD_TAGS, tags.toString(), Field.Store.NO, Field.Index.ANALYZED));
		}
		return doc;
	}
	
	private String indexExif(Image image, Document doc, String exif, Field.Store store, Field.Index index) {
		String value = image.getMeta().getString(exif);
		if (value != null) {
			doc.add(new Field(exif, value, store, index));
			return value;
		}
		return "";
	}

	@Override
	protected Term getIdTerm(Item<Image> item) {
		return new Term(FILED_INDEX_ID, item.getItem().getUuid());
	}

	@Override
	protected Analyzer getAnalyzer() {
		return analyzer;
	}

	@Override
	protected String getDefaultField() {
		return FIELD_COMBINED;
	}

	@Override
	protected List<Image> composeItems(List<Document> docs) {
		final List<Long> ids = new ArrayList<Long>();
		if (docs.isEmpty())
			return new ArrayList<Image>();
		for (Document doc : docs) {
			ids.add(Long.valueOf(doc.get(FIELD_ID)));
		}
		List<Image> images = upmRepository.executeQuery(UpmQueries.instance().images(ids));
		Collections.sort(images, new Comparator<Image>(){
			@Override
			public int compare(Image o1, Image o2) {
				Long id1 = o1.getId();
				Long id2 = o2.getId();
				int idx1 = 0, idx2 = 0;
				for (int i = 0; i < ids.size() ; i++) {
					if (ids.get(i) == id1)
						idx1 = i;
					if (ids.get(i) == id2)
						idx2 = i;
				}
				return (idx1 - idx2);
			}});
		return images;
	}

}
